﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using LCA.Community.Web.Filters;
using Microsoft.Practices.Unity;
using LCA.Community.DAL.Interfaces;
using LCA.Community.Web.Models;
using LCA.Community.DAL.Model;

namespace LCA.Community.Web.Controllers
{

    /// <summary>
    /// Controller for managing messages.
    /// </summary>
    public class MailboxController : BaseController
    {

        /// <summary>
        /// Action for showing the mailbox of the user
        /// </summary>
        /// <returns>View showing the mailbox of the user</returns>
        [SecurityFilter(SecurityRequisites="Owner,GroupOwner,Admin,GroupMember",SolvingActionParameter="id",ErrorResource="NoAuthorized")]
        [ErrorFilter(typeof(Exception), "RequestError", 1)]
        public ActionResult Index(string id)
        {
            ISocialNetworkElement element;
            var group = GroupsRepository.Get(id);
            ViewData["ID"] = id;

            if (group != null)
            {
                element = MvcApplication.Container.Resolve<GroupViewModel>(new ParameterOverrides { { "group", group } });
                ViewData["owner"] = IsGroupMember(id);
                ViewData["member"] = IsGroupOwner(id);
                ViewData["isuser"] = false;
                return View("Index", element);
            }

            var user = UsersRepository.Get(id);
            if (user != null)
            {
                element = MvcApplication.Container.Resolve<UserViewModel>(new ParameterOverrides { { "user", user } });
                bool owner = IsOwner(id);
                ViewData["owner"] = owner;
                ViewData["friends"] = !owner && IsFriend(id);
                ViewData["isuser"] = true;
                return View("Index", element);
            }

            throw new Exception("Element not found.");
        }

        /// <summary>
        /// Action for create a message
        /// </summary>
        /// <param name="id">The element id.</param>
        /// <returns>View for creating a message</returns>
        [SecurityFilter(SecurityRequisites = "Owner,GroupOwner,Admin,GroupMember", SolvingActionParameter = "id", ErrorResource = "NoAuthorized")]
        [ErrorFilter(typeof(Exception), "RequestError", 1)]
        public ActionResult Create(string id)
        {
            var group = GroupsRepository.Get(id);
            ViewData["ID"] = id;

            if (group != null)
            {
                ViewData["group"] = group;
                ViewData["owner"] = IsGroupMember(id);
                ViewData["member"] = IsGroupOwner(id);
                ViewData["isuser"] = false;
                return View("Create", new Message());
            }

            var user = UsersRepository.Get(id);
            if (user != null)
            {
                ViewData["user"] = user;
                bool owner = IsOwner(id);
                ViewData["owner"] = owner;
                ViewData["friends"] = !owner && IsFriend(id);
                ViewData["isuser"] = true;
                return View("Create", new Message());
            }

            throw new Exception("Element not found.");
        }

        /// <summary>
        /// Action for creating a message
        /// </summary>
        /// <param name="id">The element id.</param>
        /// <param name="message">The message.</param>
        /// <returns>If the message could be created returns to view of the mailbox, otherwise it returns to viw for creating a message.</returns>
        [ValidateInput(false)]
        [AcceptVerbs(HttpVerbs.Post)]
        [SecurityFilter(SecurityRequisites = "Owner,GroupOwner,Admin,GroupMember", SolvingActionParameter = "id", ErrorResource = "NoAuthorized")]
        public ActionResult Create(string id, Message message, string receivers)
        {
            var receiversList = receivers.Split(new[] { ',' }, StringSplitOptions.None).ToList();
            if (String.IsNullOrEmpty(receivers))
            {
                ModelState.AddModelError("Receivers", "Debe escribir un destinatario");
            }
            else if(receiversList.Any(r => UsersRepository.Get(r) == null))
            {
                ModelState.AddModelError("Receivers", "Uno de los destinatarios no existe.");
            }

            if (ModelState.IsValid)
            {
                message.RowKey = Guid.NewGuid().ToString();
                message.PartitionKey = id;
                message.Date = DateTime.Now;
                message.Recipents = receiversList;

                MessagesRepository.Add(message);
                return RedirectToAction("Index", new { id });
            }

            var group = GroupsRepository.Get(id);
            ViewData["ID"] = id;

            if (group != null)
            {
                ViewData["group"] = group;
                ViewData["owner"] = IsGroupMember(id);
                ViewData["member"] = IsGroupOwner(id);
                ViewData["isuser"] = false;
                return View("Create", message);
            }

            var user = UsersRepository.Get(id);
            if (user != null)
            {
                ViewData["user"] = user;
                bool owner = IsOwner(id);
                ViewData["owner"] = owner;
                ViewData["friends"] = !owner && IsFriend(id);
                ViewData["isuser"] = true;
                return View("Create", message);
            }

            throw new Exception("Element not found.");
        }


        /// <summary>
        /// Actiosn for showing details of a message
        /// </summary>
        /// <param name="id">The element id.</param>
        /// <param name="messageId">The message id.</param>
        /// <returns>View showing details of the message.</returns>
        [ErrorFilter(typeof(Exception), "UserNotFound", 1)]
        [SecurityFilter(SecurityRequisites = "Owner,GroupOwner,Admin,GroupMember", SolvingActionParameter = "id", ErrorResource = "NoAuthorized")]
        public ActionResult Message(string id, string messageId)
        {
            var group = GroupsRepository.Get(id);

            if(group != null)
            {
                ViewData["isuser"] = false;
                ViewData["member"] = IsGroupMember(UserID);
                ViewData["owner"] = IsOwner(UserID);
                ViewData["group"] = group;            
            }
            else
            {
                var user = UsersRepository.Get(id);
                if(user != null)
                {
                ViewData["isuser"] = true;
                ViewData["friends"] = IsFriend(UserID);
                ViewData["owner"] = IsOwner(UserID);
                ViewData["user"] = user;
                }
                else
                {
                    throw new Exception("Element not found");
                }
            }

            Message message = MessagesRepository.Get(messageId);
            if(!message.Read)
            {
                message.Read = true;
                MessagesRepository.Update(message);            
            }

            return View("Message", message);            
        }

        /// <summary>
        /// Action for removing a message.
        /// </summary>
        /// <param name="id">The element id.</param>
        /// <param name="messageId">The message id.</param>
        /// <returns>If the user is admin redirects to Index action of Admin controller, otherwise redirects to Index action of MailBox controller.</returns>
        [SecurityFilter(SecurityRequisites = "Owner,GroupOwner,Admin,GroupMember", SolvingActionParameter = "id", ErrorResource = "NoAuthorized")]
        public ActionResult Remove(string id, string messageId)
        {
            MessagesRepository.Delete(messageId);

            if (IsAdmin(UserID))
            {
                return RedirectToAction("Index", "Admin");
            }
            else
            {
                return RedirectToAction("Index", "Mailbox", new { id });
            }
        }

        /// <summary>
        /// Action for deleting a collection of messages.
        /// </summary>
        /// <param name="id">The element id.</param>
        /// <param name="selectedObjects">The selected objects.</param>
        /// <returns>ShowMessage partial view.</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [SecurityFilter(SecurityRequisites = "Owner,GroupOwner,Admin,GroupMember", SolvingActionParameter = "id", ErrorResource = "NoAuthorized")]
        public ActionResult Remove(string id, String[] selectedObjects)
        {
            if (selectedObjects != null)
            {
                foreach (String item in selectedObjects)
                {
                    MessagesRepository.Delete(item);
                }
            }

            var partialView = new PartialViewResult();
            partialView.ViewName = "ShowMessages";
            partialView.ViewData.Model = MessagesRepository.GetInbox(id);
            return partialView;
        }

        /// <summary>
        /// Action for creating a new help request.
        /// </summary>
        /// <param name="id">The user id.</param>
        /// <param name="volunteerId">The volunteer id.</param>
        /// <returns>View for creating a new help request.</returns>
        [SecurityFilter(SecurityRequisites = "Owner,GroupOwner,Admin,GroupMember", SolvingActionParameter = "id", ErrorResource = "NoAuthorized")]
        public ActionResult NewHelpRequest(string id, string volunteerId)
        {
            List<User> volunteers;

            if (!String.IsNullOrEmpty(volunteerId))
            {
                var volunteer = UsersRepository.Get(volunteerId);
                if (volunteer == null)
                {
                    throw new Exception("User not found");
                }

                volunteers = new List<User> { volunteer };
            }
            else
            {
                volunteers = UsersRepository.GetVolunteersOfUser(UserID);
            }

            ViewData["myvolunteers"] = volunteers;
            ViewData["isuser"] = true;
            ViewData["friends"] = IsFriend(UserID);
            ViewData["owner"] = IsOwner(UserID);
            ViewData["user"] = UsersRepository.Get(UserID);
            ViewData["ID"] = UserID;

            return View("NewHelpRequest", new Message());
        }

        /// <summary>
        /// Action for creating a new help request.
        /// </summary>
        /// <param name="id">The user id.</param>
        /// <param name="message">The message.</param>
        /// <returns>If the request could be sent return to Index action of Mailbox controller, otherwise return to the view for creating a new help request.</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateInput(false)]
        [SecurityFilter(SecurityRequisites = "Owner,GroupOwner,Admin,GroupMember", SolvingActionParameter = "id", ErrorResource = "NoAuthorized")]
        public ActionResult NewHelpRequest(string id, Message message, string receiver)
        {
            message.Recipents = new List<string>() { receiver };

            if (ModelState.IsValid)
            {
                message.Date = DateTime.UtcNow;
                message.RowKey = Guid.NewGuid().ToString();
                message.PartitionKey = UserID;
                message.Subject = string.Format("Help Request: {0}", message.Subject);

                MessagesRepository.Add(message);

                ViewData["owner"] = IsOwner(UserID);
                ViewData["user"] = UsersRepository.Get(UserID);
                return RedirectToAction("Index", "Mailbox", new { id });
            }
            else
            {
                ViewData["myvolunteers"] = new List<User> { UsersRepository.Get(receiver) };
                ViewData["isuser"] = true;
                ViewData["friends"] = IsFriend(UserID);
                ViewData["owner"] = IsOwner(UserID);
                ViewData["user"] = UsersRepository.Get(UserID);
                ViewData["ID"] = UserID;

                return View("NewHelpRequest", message);
            }

        }

        [Dependency]
        public IMessagesRepository MessagesRepository { get; set; }
        [Dependency]
        public IUsersRepository UsersRepository { get; set; }
    }
}
